package com.qf.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.qf.dao.XcUserRepository;
import com.qf.pojo.po.XcUser;
import com.qf.pojo.req.XcUserReq;
import com.qf.pojo.resp.BaseResp;
import com.qf.service.UserService;
import com.qf.utils.EmailUtil;
import com.qf.utils.Jwtutils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    XcUserRepository xcUserRepository;

    @Autowired
    EmailUtil emailUtil;

    @Autowired
    RedisTemplate redisTemplate;

    //判断邮箱是否重复
    @Override
    public BaseResp validataEmail(String email) {

        XcUser ByEmailUser=xcUserRepository.findByEmail(email);

        //判断查询结果
        if (ByEmailUser!=null){

            return new BaseResp(1,"该邮箱已注册",null,null);
        }

        return new BaseResp(0,"该邮箱未注册",null,null);
    }

    //验证用户名是否重复  密码是否一致前端验证
    @Override
    public BaseResp validataUserName(String username) {

        XcUser ByNameUser= xcUserRepository.findByUserName(username);

        //判断查询结果
        if (ByNameUser!=null){

            return new BaseResp(1,"该用户名已经存在",null,null);
        }

        return new BaseResp(0,"该用户名可用",null,null);
    }

    //向前台发送邮件验证码
    @Override
    public BaseResp getCode(String email) {

        //现在后台拿到了前台给的邮箱 要向这个邮箱地址发送验证码
        //调用工具类发送邮件同时返回map验证码用来对比
        //此时这个send中存放的是key为code，value为四位验证码的map,此时验证码已经发送给用户了
        Map send=emailUtil.send(email);

        //存储redis
        redisTemplate.opsForValue().set(email,send.get("code").toString());

        //设置验证码存活时间 五分钟 expir:到期   对象 时长 时间类型
        redisTemplate.expire(email,300, TimeUnit.SECONDS);

        return new BaseResp(0,"发送成功",null,null);
    }

    //用户注册
    @Override
    public BaseResp registry(XcUserReq xcUserReq) {

        //点击注册后先校验之前所填信息是否修改
        XcUser ByEmailUser=xcUserRepository.findByEmail(xcUserReq.getEmail());
        //判断邮箱查询结果
        if (ByEmailUser!=null){
            return new BaseResp(1,"该邮箱已注册",null,null);
        }
        XcUser ByNameUser= xcUserRepository.findByUserName(xcUserReq.getUserName());
        //判断用户名查询结果
        if (ByNameUser!=null){
            return new BaseResp(1,"该用户名已经存在",null,null);
        }

        //验证码比对
        //1.从前端传过来的对象中获取验证码
        String code=xcUserReq.getCode();

        //2.对比
        //2.0 先判断是否在redis中还存在code(验证码超时)
        boolean fristcode=redisTemplate.hasKey(xcUserReq.getEmail());

        if (!fristcode){
            return new BaseResp(1,"验证码失效",null,null);
        }


        //2.2 从redis中获取code 其中xcUserReq.getEmail()就是email,为了获得redis存储的key 然后用key来获取值
        Object Rediscode=redisTemplate.opsForValue().get(xcUserReq.getEmail());

        if (!Rediscode.toString().equals(code)){

            return new BaseResp(1,"验证码填写错误",null,null);
        }

        //3.对比通过存储数据库
        //3.1 因为传过来的实体类型是XcUserReq，但是往数据库中存是要存XcUser类型
        XcUser PojoXcUser=new XcUser();

        //3.2将注册信息写入到PojoliveUser中（此时信息还没有写入）  source:来源  target：目标
        BeanUtils.copyProperties(xcUserReq,PojoXcUser);

        //3.3将写入的信息保存并且刷新（信息在这一步已经写入了数据库）
        PojoXcUser.setCreateTime(new Date());
        PojoXcUser.setUpdateTime(new Date());
        XcUser SqlPojoliveUser=xcUserRepository.saveAndFlush(PojoXcUser);

        //3.4对比数据库是否存在该条用户注册信息
        if (SqlPojoliveUser !=null) {

            return new BaseResp(0,"注册成功",null,null);
        }

        return new BaseResp(1,"注册失败，该用户已注册",null,null);

    }


    //用户登录
    @Override
    public BaseResp login(XcUserReq xcUserReq) {

        //请输入邮箱
        String yanzhengemail=xcUserReq.getEmail();

        if(yanzhengemail==""){

            return new BaseResp(1,"请输入登陆邮箱",null,null);
        }

        //请输入密码
        String yanzhengpassword=xcUserReq.getPassword();

        if(yanzhengpassword==""){

            return new BaseResp(1,"请输入密码",null,null);
        }

        //根据前台传过来的数据(邮箱)查询数据库中的用户
        XcUser xcUser=xcUserRepository.findByEmail(xcUserReq.getEmail());

        if (xcUser==null){

            return new BaseResp(1,"该用户不存在",null,null);
        }

        //对比密码
        if (!xcUser.getPassword().equals(xcUserReq.getPassword())){

            return new BaseResp(1,"密码错误",null,null);
        }

        //4.生成Jwt
        Jwtutils jwtutils=new Jwtutils();

        Map map=new HashMap();

        //将xcUser的id放入集合中（这个id是数据库的id）
        map.put("xcUserid",xcUser.getId());

        //4.1创建令牌 生成token
        String token=jwtutils.createToken(map);

        //将成功登录的用户实体转成json对象放到redis当中
        redisTemplate.opsForValue().set(token,xcUser);

        return new BaseResp(0,"登陆成功",null,token);

    }

    //通过邮箱修改密码
    @Override
    public BaseResp updatepasswordbyemail(XcUserReq xcUserReq) {

        //1.用户未登录时通过邮箱修改密码
        //1.1获取前台邮箱信息
        String email=xcUserReq.getEmail();

        //判断是否输入邮箱
        if (email==""){

            return new BaseResp(1,"请输入邮箱",null,null);
        }


        //根据获取到的邮箱去数据库查询用户
        XcUser xcUser=xcUserRepository.findByEmail(email);

        //判断用户是否存在
        if (xcUser==null){
            return new BaseResp(1,"该邮箱尚未注册",null,null);
        }

        //判断验证码是否正确
        String code=xcUserReq.getCode();

        //先判断是否在redis中还存在code(验证码超时)
        boolean fristcode=redisTemplate.hasKey(xcUserReq.getEmail());

        if (!fristcode){
            return new BaseResp(1,"验证码失效",null,null);
        }

        //2.2 从redis中获取code 其中xcUserReq.getEmail()就是email,为了获得redis存储的key 然后用key来获取值
        Object Rediscode=redisTemplate.opsForValue().get(xcUserReq.getEmail());

        if (!Rediscode.toString().equals(code)){

            return new BaseResp(1,"验证码填写错误",null,null);
        }

        //如果该用户存在且验证码通过则将数据库中的用户密码修改为前台传过来的密码
        xcUser.setPassword(xcUserReq.getPassword());

        xcUserRepository.saveAndFlush(xcUser);

        return new BaseResp(0,"重置密码成功",null,null);
    }

    // 当用户访问其他页面时解析请求头中的token来获取登录用户信息
    @Override
    public BaseResp findUserByToken(String token) {

        //返回值是否有这个token 有则代表登陆时存储成功并且存储了该对象
        Boolean aBoolean=redisTemplate.hasKey(token);

        if (!aBoolean){

            return new BaseResp(1,"用户未登录",null,null);
        }

        //如果有这个token则通过--获取用户的姓名 此时这个o是当初存储的用户信息
        Object o=redisTemplate.opsForValue().get(token);

        //因为当初存储的是json 现在要返回实体 所以在解析回来xcuser对象
        String s= JSONObject.toJSONString(o);

        //这两行是json语法异常--这样转换一下 如果有异常则放开看看
//      Object s1=JSON.parse(s);
//      String s2=s1.toString();

        XcUser xcUser=JSONObject.parseObject(s, XcUser.class);

        return new BaseResp(0,"查询成功",null,xcUser);
    }

    //登出
    @Override
    public BaseResp exit(HttpServletRequest request) {

        //从请求的头部信息获得token
        String token=request.getHeader("token");

        //在redis中按token名字查找token
        Boolean aBoolean = redisTemplate.hasKey(token);

        if (aBoolean){

            Boolean delete = redisTemplate.delete(token);

            if (delete){
                return new BaseResp(0,"删除缓存成功",null,null);
            }
        }
        return new BaseResp(1,"删除失败",null,null);
    }

}



